%changes for SOS Release 3.2 by M. Ranft marked with "29.10.91mr"

\section{Interface to C++}
\label{sec:Interface to C++}

For each SOS schema, an internal representation of the schema in
terms of instances of the meta classes is generated due to a successful
compilation process. From this representation, a variety of interfaces is
intended to be generated.
This section describes the embedding of the SOS schema language into C++
(see \cite{ATT89} or \cite{GNU90}).
In the following, it is only considered the case that as well the implementation
as the tool that makes use of this implementation is written in C++.
First, the structure of
the C++ source files that are generated or must be provided is described.
Then, for each language construct of the schema language the mapping into
constructs of C++ is stated.
At last, it is described how to implement methods specified in an SOS schema.

\subsection{The Source File Structure}

For each SOS schema module a separate C++ interface and implementation
file is generated from the internal representation of the schema in
the object base.
The interface consists of type and class definitions that may be 
used by other C++ implementation modules. 
All user defined methods and operations must be
implemented separately. If the schema defines external types, the
generated interface includes a file with the definition of these
types.
This implementation as well as the generated implementation
can then be compiled
and linked to all applications that make use of the given schema module.
The embedding of schemas into C++ is sketched in Figure~\ref{fig:CC}. 

\begin{figure}[htb]
\begin{center}
\
\vspace*{2mm}
\psfig{figure=figures/cplusplus.epsi,height=11.6cm,width=14.3cm}
\vspace*{2mm}
\end{center}
\caption{\label{fig:CC}Embedding of SOS into C++}
\end{figure}

The generated interface files for a schema with name
\verb@<s>@ are \verb@<s>_sos.h@ and \verb@<s>_use.h@.
The file \verb@<s>_sos.h@ is only needed by the implementor of
the methods defined in the schema, whereas \verb@<s>_use.h@ makes up
the interface to other C++ programs. 
As a further result of the compilation process an implementation file
\verb@<s>_sos.c@ is generated, that contains the implementation of the
predefined function methods, e.g. methods to access the object base.
This file, as well as the files containing the implementation of the
remaining methods provided by the schema implementor, must be compiled.
The resulting object files can then be statically linked to an executable.
Programs that are not linked with these object files but access instances
of classes defined in schema \verb@<s>@ will have to load these files
dynamically at the time the first instance of a type declared in schema
\verb@<s>@ is accessed.

The definition of the external types, if any, is expected in a file named
\verb@<s>_ext.h@.  This file must also be provided, if the schema
\verb@<s>@ contains a {\tt with extern} declaration.

\subsection{The Mapping of Language Constructs}

\subsubsection{External Types}
\label{sec:External Types}

For each external type named \verb@<E>@, the following
two functions are generated, which convert a value of type
\verb@<E>@ into its object representation and vice versa:

\begin{verbatim}
   sos_Object make_<E>_object (E);
   E          make_<E>        (sos_Object);
\end{verbatim}

For the conversion from \verb@sos_Object@ to \verb@<E>@
a dynamic type check is performed.
The object that results from \verb@make_<E>_object@
is of the class \verb@sos_Scalar_object@; this class
is declared in the kernel schema and described in
Appendix~\ref{sec:Manual Pages}.

The generated functions will make use of some conversion operations that
must be provided by the schema implementor.
For this purpose, for each external type named \verb@<E>@, the file
\verb@<schema-name>_ext.h@ must define a C++ type with the same name together
with following functions:
\begin{verbatim}
void bcopy_from_<E> (void *e, void *c)
void bcopy_to_<E>   (void *e, void *c)
\end{verbatim}

These functions convert a value of type \verb@<E>@ (pointed to by the
parameter \verb@e@) to its standard representation
% 29.10.91mr
(see also Section \ref{sec:The Scalar Types})
% end 29.10.91mr
of \verb@n@ bytes
(pointed to by the parameter \verb@c@) and vice versa.%
\footnote{An implementation may assume that both addresses are properly aligned
          according to the requirements of type \verb@<E>@.}
\verb@n@ is the size of the external type as denoted
in the external type declaration in the schema. Note that a standard
representation of an external type is needed to achieve a language and
machine independent storage of objects.

Additionally two functions that convert an external type into
an {\tt sos\_String} must be provided, to enable the development
of generic I/O routines.%
\footnote{e.g. the methods {\tt string\_from\_extern\_object} and
          {\tt extern\_object\_from\_string} of class
          {\tt cci\_Schema\_impl} (see Appendix~\ref{sec:Manual Pages}).}
\begin{verbatim}
sos_String make_string_from_<E>_object (sos_Object);
sos_Object make_<E>_object_from_string (sos_String);
\end{verbatim}

By convention, the string returned by the first conversion operation has to be
created in the {\tt TEMP\_CONTAINER}. It is up to the caller of this function 
to destroy this string object. Also by convention, the conversion operations
should return {\tt NO\_OBJECT} on failure.

{\bf Example:}

For the type \verb@sos_Char@, whose standard representation takes one byte,
these operations might look as follows:

\begin{verbatim}
inline void bcopy_from_sos_Char (void *sos_ch, void *c)
{  *(char*)c = (char*)(sos_Char*)sos_ch; }
inline void bcopy_to_sos_Char (void *sos_ch, void *c)
{  *(sos_Char*)sos_ch = (char*)c; }
\end{verbatim}
\begin{verbatim}
sos_String make_string_from_sos_Char_object (sos_Object c)
{  sos_Char s[2];
   s[0] = make_sos_Char (c);  s[1] = '\0';
   sos_String result = sos_String::create (TEMP_CONTAINER);
   result.assign_Cstring (s);
   return result;
}

sos_Object make_sos_Char_object_from_string (sos_String s)
{  sos_Cstring s1 = s.make_Cstring();
   sos_Object  result;
   if (strlen (s1) == 1)  result = make_sos_Char_object (s1[0]);
   else                   result = NO_OBJECT;
   delete s1;
   return result;
}
\end{verbatim}

$\Box$

\subsubsection{Enumeration Types}
\label{sec:Enumeration Types}

An enumeration type declaration is mapped to a C++ enumeration type with the
same literals. As for external types, for an enumeration type with name
\verb@<E>@ the functions

\begin{verbatim}
   sos_Object make_<E>_object (E);
   E          make_<E>        (sos_Object);
\end{verbatim}

are generated.

\subsubsection{Typedef Declarations}

For each typedef declaration a corresponding 
C++ type with the same name is defined.

\subsubsection{Class Types}

For each class declaration appearing in the schema, the SOS interface generator
for the C++ programming language generates a C++ class with the same name.
Objects of this C++ class are references to persistent
objects of the corresponding schema class.
The methods that are declared within the schema must be implemented
in terms of the generated C++ class interface.
%
%For the generated auxiliary classes (\verb@_C@), the C++ inheritance
%structure is the same as for the classes from the SOS schema.
%For the corresponding classes (\verb@C@), the inherited
%methods are expanded, that means all inherited methods are explicitly declared
%as methods of the C++ class.
%Implicit conversion operators to the super classes
%of \verb@C@ are generated. Thus, it is possible to use an object of class
%\verb@C@ as argument to a function with argument type \verb@B@, if \verb@B@ is
%defined as a supertype of \verb@C@ in the schema.
%For the usage of the class, there is no
%visible difference between using inheritance or expanding the declared
%methods.

Due to the similarity of an SOS schema and C++ class declarations, there are very
little differences between programming pure C++ and programming with SOS classes.
The main difference is that during method implementation
you must never call other methods of the same class directly.
Instead you always have to access methods of a class from inside of
the implementation of another method by applying them to \verb@self@.

The access specifiers \verb@public@, \verb@protected@ and \verb@private@
are mapped to the identical specifiers in C++ as in the SOS schema.
SOS allows moreover for components to declare different access specifiers for
reading and writing.
This leads to a mapping in C++ with \verb@get_@ and \verb@set_@ methods
of different categories.

The ``function-kind'' specifier \verb@static@ is mapped to the
equivalent specifier in C++ with the same name and syntax.
%The function-kind specifier \verb@abstract@ is mapped to the abstract function
%specifiers (\verb@=0@) of C++.
The concept of \verb@definite@ functions doesn't have any equivalent in C++.
The assertion that methods marked with this keyword are not redefinable in subclasses
is controlled only by the SOS schema compiler.
Therefore, no mapping to a C++ construct is needed, but for efficiency
reasons \verb@definite@ functions are mapped to nonvirtual functions,
whereas all other non-static functions must be mapped to virtual ones
in the C++ interface
(cf. Section~\ref{sec:Function Methods}).

{\bf Example:}

%\pagebreak[4]
\begin{verbatim}
SOS declaration:

   class B
   {       
   public:
      definite void g ();
   };

   class C : B
   {       
      void p1();
      void p2();
   public, private set:
      A comp;
   public:
      void f (A);
   };
\end{verbatim}
\pagebreak[3]
\begin{verbatim}
Generated C++ interface:
(method implementations intimated by three dots are generated)

   class B
   {       
   public:
      void g ();

      static B create (sos_Container)  {...}
      static B copy  (B, sos_Container) {...}
      static B clone (B, sos_Container) {...}
      static B make (sos_Object) {...}
      ...
   };

   class C : virtual public B
   {
   private:
      virtual void p1();
      virtual void p2();
      virtual void set_comp (A) {...}
   public: 
      virtual void f (A);
      virtual A get_comp () {...}

      static C create (sos_Container)  {...}
      static C copy  (C, sos_Container) {...}
      static C clone (C, sos_Container) {...}
      static C make (sos_Object) {...}
      ...
   };

   Implementation (not generated)

   void B::g()  {...}
   void C::p1() {...; self.set_comp (x); ...}
   void C::p2() {...; self.p1(); ...}
   void C::f(A) {...}

Application:

   A a;
   C c1, c2;
   ...
   a = c2.get_comp ();
   c1.f(a);
   c1.g();
\end{verbatim}

$\Box$

Note, that the description given here states only a logical mapping to C++ class
declarations that a user must have in mind when implementing its application. 
Users that are interested in the code that is physically generated
are referred to the documentation of the implementation of the SOS environment
\cite{SOSI91}.
%
%The C++ methods whose implementation is sketched by \verb@{...}@ in
%the generated part are automatically
%implemented by the C++ generator. The others must be implemented; note
%that they are methods of the auxiliary classes, whose name begins
%with an underscore.

The methods \verb@create@, \verb@clone@, \verb@copy@, and \verb@make@ 
exist for all classes (see Section~\ref{sec:Predefined Methods}).

\subsubsection{Generic Class Instantiations}

The declaration of class instantiations is the same as for any other class
considering the rules for composing the name of the instantiation
and the rules for replacing the formal generic types with the actual ones.
This means, for each class instantiation 
\verb@G<T1, ..., Tn>@ occurring either explicitly
in a typedef declaration or implicitly as a type name
a C++ class declaration with the name associated to this class instantiation
(\verb@T1_..._Tn_G@) is declared.
In this declaration, each occurrence of a type parameter
\verb@Pi@ in the generic class declaration for \verb@G@ is replaced by
the actual type \verb@Ti@.

For example, consider the following SOS declaration of a generic class:

\begin{verbatim}
class Generic <X,Y>
{  
   X att;
   Y func (X);
};
\end{verbatim}

An instantiation of that class:
\begin{verbatim}
typedef Generic<T1,T2> TG;
\end{verbatim}

is translated into the following C++ type declaration:
\begin{verbatim}
class T1_T2_Generic : virtual public sos_Object
{  ...
   virtual T1    get_att();
   virtual void  set_att(T1);
   virtual T2    func (T1);
};
typedef T1_T2_Generic TG;
\end{verbatim}

Note, that the naming conventions apply recursively, that means
the type instantiation \verb@Generic<List<T1>,T2>@ is declared as
\verb@T1_List_T2_Generic@.

{\bf Example:}
%\subsubsection{Example}
%\label{sec:cplusplus Example}

Let us illustrate the described SOS to C++ mapping using the
generic class \verb@Set@ that is available as a predefined class 
in the SOS environment (see Section~\ref{sec:The SOS Environment}):

\begin{verbatim}

schema agg
{
   ...

   class Collection<Entity> : sos_Aggregate {...};

   class Set<Entity> : Collection<Entity>
   {
   public:
      bool is_element (Entity);
      void insert (Entity);
      void operator+= (Set<Entity>);   // union
      ...
   };
}
\end{verbatim}

For an example of the mapping to C++ classes 
have a look at the following application schema that is using
the predefined class \verb@Set@ from schema \verb@agg@.

\begin{verbatim}
with agg
schema Sample
{
   class sosFile {...};

   class sosDirectory
   {
      Set<sosFile>       files;
      Set<sosDirectory>  dirs;
   public:
      Set<sosFile>       ls ();
      void               rmdir();
      ...
   };
}
\end{verbatim}

The SOS schema \verb@Sample@ will be translated into a C++ interface as follows:
\begin{verbatim}

class sosFile : virtual public sos_Object {...};

class sosFile_Set : virtual public sosFile_Collection
{
public:
   virtual bool is_element (sosFile);
   virtual void insert (sosFile);  
   virtual void operator+= (sosFile_Set);
   ...
};

class sosDirectory_Set : virtual public sosDirectory_Collection { ... };

class sosDirectory : virtual public sos_Object
{ 
   virtual sosFile_Set       get_files ();
   virtual void              set_files (sosFile_set);
   virtual sosDirectory_Set  get_dirs ();
   virtual void              set_dirs (sosDirectory_set);
public:
   virtual sosFile_Set       ls ();
   virtual void              rmdir;
   ...
};
\end{verbatim}

$\Box$

\subsubsection{Union Types}

For each union type {\tt U} uniting types $T_1,\ldots~,T_n$ a C++ class
declaration with the same name and
implicit type conversions from $T_i$ ($1\le~i\le~n$) to $U$
are generated. The generated C++ class $U$ is derived from class
\verb@sos_Object@.

{\bf Example:}

\begin{verbatim}
SOS declaration:

   union U { A, B, C };

\end{verbatim}
\pagebreak[3]
\begin{verbatim}
Generated C++ interface:

   class U : public sos_Object
   {       
   public:
      U (A);
      U (B);
      U (C);
      static U make (sos_Object);
      ...
   };

\end{verbatim}

$\Box$

The class method {\tt make} allows the conversion of object references
to type $U$, provided the given object actually is of type $U$.

\subsubsection{Type Objects}
\label{sec:Type Objects}

Each type declaration in the schema module is translated into one
C++ type declaration with the same name. In addition, for each type
\verb@<T>@ there is a C++ constant \verb@<T>_type@ which denotes the
corresponding (persistent) object of the base type that the schema compiler has
generated. It can be used to check the actual type of an object. This way
of dynamic type evaluation allows a case distinction by the type of an
object.

Note that for a type declared by
\begin{verbatim}
   typedef A B;
\end{verbatim}
the constant \verb@B_type@ denotes the base type object for \verb@A@, that
means \verb@A_type == B_type@.

{\bf Example:}

The following C++ code checks, whether an object \verb@o@ that is statically
declared of type \verb@sos_Object@ actually is of type \verb@sos_String@;
if so, it is explicitly converted to this type, and the method
\verb@make_Cstring@
of this type is called. The conversion is necessary, since the method
is no method of class \verb@sos_Object@, so \verb@o.make_Cstring()@ would
produce a C++ compile time error.

\begin{verbatim}
   sos_Object o;
   ...
   if (o.has_type (sos_String_type))
   {  sos_String  s  = sos_String::make (o);
      sos_Cstring cs = s.make_Cstring();
      cout << cs;
      delete cs;
   }
\end{verbatim}

$\Box$

\subsection{The C++ Environment}
\label{sec:The C++ Environment}

Of eminent importance for the incremental loading of methods
is an initializition routine that should be executed at the 
start of every program.
This routine will be introduced in the next section.
Furthermore some iterator macros and a C++ class to facilitate string
management are presented in the following sections.

\subsubsection{Initialization}
\label{sec:Initialization}

As usual for C++-programs a module containing a {\tt main} routine
must be linked to the method implementations.
To enable the incremental loading of method implementations, such {\tt main}
routines should start with a call of the function {\tt sos\_init} to which the
command line arguments must be passed:
\begin{verbatim}
   int main (int argc, char *argv[])
   {
      sos_init (argc, argv);
      ...
      return 0;
   }
\end{verbatim}

\subsubsection{Iterators}
\label{sec:Iterators}

The macros {\tt agg\_iterate(s, e)} and {\tt agg\_iterate\_end(s, e)}
implement iterators for arbitrary collections.
The macros must surround the body over which the loop iterates.
\verb@s@ and \verb@e@ denote the collection
and the element, respectively.
They must both be declared with the correct types.
The actual expression for \verb@e@ must be a variable, optionally
preceded with its type; the actual expression for \verb@s@ should be a
variable, since it might be evaluated more than once.

The following example calls the function \verb@f@ for all elements
of a collection \verb@c@:

\begin{verbatim}
C c = ...;

agg_iterate (c, E e)
{ 
   f (e);
}
agg_iterate_end (c, e);
\end{verbatim}

For iterating over a collection in the reverse direction 
a pair of similar iterators
named {\tt agg\_iterate\_reverse[\_end](s, e)} are provided.

Furthermore, the macros {\tt agg\_iterate\_association[\_end](s, key, info)}
implement iterators over associations (in particular over mappings).

Finally, the macros \verb@agg_iterate_double[_end](s1, e1, s2, e2, comp)@
implement iterators over two collections,
where \verb@comp@ is an integer variable, which is set to
\verb@-1@, \verb@1@, or \verb@0@, depending on whether 
only the first, second, or both collections are exhausted when the
iteration terminates. The following example implements a
``lexicographic'' comparison of the two collections {\tt s1} and
{\tt s2} assuming a type {\tt Ordered} for which an operator
\verb@<@ is defined:

\begin{verbatim}
int compare (Ordered_Collection s1, Ordered_Collection s2)
{ 
   int result;

   agg_iterate_double (s1, Ordered e1, s2, Ordered e2, result)
   {  
      if (e1 < e2) return -1;
      else if (e2 < e1) return 1;
   }
   agg_iterate_double_end (s1, e1, s2, e2, result);

   return result;
}
\end{verbatim}

\subsubsection{The Class smg\_String}
\label{sec:The Class smg_String}

The purpose of the class {\tt smg\_String} is the handling of C++
character strings with the option to perform automatic storage management.
A character string that is handled by any {\tt smg\_String} may be
managed or not managed;
a managed character string will be deleted as soon as it is no longer
needed by an {\tt smg\_String}.
Assignment and copying of {\tt smg\_Strings} is controlled pointer assignment,
that means it does not copy the character string (but only increments a
reference counter).
An {\tt smg\_String} is in general constructed from a C character string or
an {\tt sos\_String}.
The scope of a character string is the period from its allocation up to
its deallocation or, for a statically declared character array,
the period from its declaration up to the end of the enclosing block;
the scope of a string literal is the whole program.
The scope of an {\tt smg\_String } is the period from its construction up
to its destruction (in the sense of C++).
The way in which a character string is handled by an
{\tt smg\_String} depends on the access specification given to the constructor.
For a detailed explanation refer to Appendix~\ref{sec:Manual Pages}.

